package routes

import (
	"fmt"
	"gotask/blocks"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"github.com/go-session/gin-session"
)

type UserInfo struct {
	UserName string `json:"username"`
	PassWord string `json:"password"`
}

func respJson(c *gin.Context, resp *RespInfo) {

	//错误码重新组织
	resp.Msg = GetCodeMsg(resp.Code)
	//发消息给浏览器
	c.JSON(http.StatusOK, resp)
}

func Register(c *gin.Context) {
	//3. 组织响应消息  defer
	resp := RespInfo{
		Code: RCODE_OK,
	}
	defer respJson(c, &resp) //延迟执行
	//1. 解析请求消息
	var userinfo UserInfo
	err := c.ShouldBindJSON(&userinfo)
	if err != nil {
		resp.Code = RCODE_PARAMERR
		fmt.Println("failed to ShouldBindJSON", err)
		return
	}
	fmt.Println("register:", userinfo)
	//2. 调用合约注册接口
	err = blocks.Register(userinfo.UserName, userinfo.PassWord)
	if err != nil {
		fmt.Println("Failed to Register", err)
		resp.Code = RCODE_BCKERR
		return
	}

}

func Login(c *gin.Context) {
	//3. 组织响应消息  defer
	resp := RespInfo{
		Code: RCODE_OK,
	}
	defer respJson(c, &resp) //延迟执行
	//1. 解析请求消息
	var userinfo UserInfo
	err := c.ShouldBindJSON(&userinfo)
	if err != nil {
		resp.Code = RCODE_PARAMERR
		fmt.Println("failed to ShouldBindJSON", err)
		return
	}
	fmt.Println("Login:", userinfo)
	//2. 调用合约注册接口
	ok, err := blocks.Login(userinfo.UserName, userinfo.PassWord)
	if err != nil {
		fmt.Println("Failed to Login", err)
		resp.Code = RCODE_BCKERR
		return
	}
	if !ok {
		resp.Code = RCODE_LOGINERR
		fmt.Println("user or password err")
		return
	}
	//session保存
	store := ginsession.FromContext(c)
	store.Set("username", userinfo.UserName)
	store.Set("password", userinfo.PassWord)
	err = store.Save()
	if err != nil {
		c.AbortWithError(500, err)
		resp.Code = RCODE_UNKNOWNERR
		return
	}

}

func Issue(c *gin.Context) {
	//3. 组织响应消息  defer
	resp := RespInfo{
		Code: RCODE_OK,
	}
	defer respJson(c, &resp) //延迟执行
	//1. 解析请求消息
	var usertask blocks.UserTask
	err := c.ShouldBindJSON(&usertask)
	if err != nil {
		resp.Code = RCODE_PARAMERR
		fmt.Println("failed to ShouldBindJSON", err)
		return
	}
	fmt.Println("Issue:", usertask)
	//从session获取用户和密码
	store := ginsession.FromContext(c)
	username, ok1 := store.Get("username") //获取的是interface类型
	password, ok2 := store.Get("password")
	if !ok1 || !ok2 {
		c.AbortWithStatus(404)
		resp.Code = RCODE_UNKNOWNERR
		return
	}
	//2. 调用合约注册接口
	err = blocks.Issue(username.(string), password.(string), usertask.TaskName, usertask.Bonus)
	if err != nil {
		fmt.Println("Failed to Issue", err)
		resp.Code = RCODE_BCKERR
		return
	}

}

func Update(c *gin.Context) {
	//3. 组织响应消息  defer
	resp := RespInfo{
		Code: RCODE_OK,
	}
	defer respJson(c, &resp) //延迟执行
	//1. 解析请求消息
	var usertask blocks.UserTask
	err := c.ShouldBindJSON(&usertask)
	if err != nil {
		resp.Code = RCODE_PARAMERR
		fmt.Println("failed to ShouldBindJSON", err)
		return
	}
	fmt.Printf("Update:%+v\n", usertask)
	//从session获取用户和密码
	store := ginsession.FromContext(c)
	username, ok1 := store.Get("username") //获取的是interface类型
	password, ok2 := store.Get("password")
	if !ok1 || !ok2 {
		c.AbortWithStatus(404)
		resp.Code = RCODE_UNKNOWNERR
		return
	}
	//2. 调用合约注册接口
	//将任务的string类型转换为int64类型
	task_id, err := strconv.ParseInt(usertask.TaskID, 10, 64)
	if err != nil {
		fmt.Println("Failed to ParseInt at Update", err)
		resp.Code = RCODE_UNKNOWNERR
		return
	}
	err = blocks.Update(username.(string), password.(string), usertask.Comment, usertask.Status, task_id)
	if err != nil {
		fmt.Println("Failed to Issue", err)
		resp.Code = RCODE_BCKERR
		return
	}
}

func Tasklist(c *gin.Context) {
	//3. 组织响应消息  defer
	resp := RespInfo{
		Code: RCODE_OK,
	}
	defer respJson(c, &resp) //延迟执行
	//1. 解析请求消息
	page := c.Query("page")
	ipage, err := strconv.Atoi(page)
	if err != nil {
		fmt.Println("failed to strconv.Atoi at Tasklist", err)
		resp.Code = RCODE_PARAMERR
		return
	}

	fmt.Println("Tasklist: page = ", ipage)

	//2. 查询任务列表

	tasks, err := blocks.Tasklist()
	if err != nil {
		fmt.Println("failed to blocks.Tasklist at Tasklist", err)
		resp.Code = RCODE_BCKERR
		return
	}

	fmt.Println("tasklist:", tasks)

	//3. 组织响应的格式数据
	//计算分页的数据
	begin := (ipage - 1) * 10
	end := ipage * 10

	if end > len(tasks) {
		end = len(tasks)
	}

	rdata := struct {
		Total int               `json:"total"`
		Data  []blocks.UserTask `json:"data"`
	}{
		Total: len(tasks),
		Data:  tasks[begin:end],
	}

	resp.Data = rdata

}
